
#include <stdlib.h>
#include <stdio.h>
#include "pcb.h"

// Initializes a new program status block with the given parameters.
PCB pcb_init(int the_pid, int the_next_step, Process the_process,
             CPUPtr the_cpu)
{
    PCB temp = (PCB) malloc(sizeof(PCBStr));
    if (temp == NULL)
    {
        perror("malloc failure on pcb_init");
        exit(EXIT_FAILURE);
    }
    temp->pid = the_pid;
    temp->proc = the_process;
    temp->next_step = the_next_step;
    temp->cpu = the_cpu;

    return temp;
}

// Frees up the memory used by the PCB.
void pcb_destroy(PCB the_pcb)
{
    if (the_pcb != NULL)
    {
        process_destroy(the_pcb->proc);
        //cpu_destroy(the_pcb->cpu); //Removed to avoid double free issues.
        free(the_pcb);
        the_pcb = NULL;
    }
}

// Sets the PCB's blocked queue.
void pcb_set_blocked_queue(PCB the_pcb, PQueue *the_blocked_queue)
{
    the_pcb->waiting_on = the_blocked_queue;
}

void *pcb_run(void *the_pcb)
{
    PCB temp = (PCB)the_pcb;
    int current_step = temp->next_step;
    while(temp->cpu->pc_reg < temp->proc->no_steps)
    {
        pthread_mutex_lock(temp->cpu->run_lock);
        while(temp->cpu->run_var != temp->pid)
        {
            pthread_cond_wait(temp->cpu->run_cond, temp->cpu->run_lock);
        }
        if (temp->cpu->run_var == EXIT_VAR)
        {
            pthread_exit(NULL);
        }
        //printf("inside thread %d\n", temp->next_step);
        pthread_mutex_lock(temp->cpu->step_lock);
        if (current_step != temp->cpu->pc_reg)
        {
            current_step = temp->cpu->pc_reg;
            printf("The current process running is %d.\n", temp->pid);
            printf("Current step of this process is %d.\n", current_step);
            if (current_step == temp->proc->no_steps)
            {
                temp->cpu->pc_reg = 0;
            }
        }
        pthread_mutex_unlock(temp->cpu->step_lock);
        pthread_mutex_unlock(temp->cpu->run_lock);
    }

    printf("test ended.");

    return NULL;
}
